home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 275_02 / lcau41.c < prev    next >
Encoding:
C/C++ Source or Header  |  1980-01-01  |  28.1 KB  |  962 lines

  1.  
  2. /* lcau41.c                */
  3. /* (4,1) Linear Cellular Automaton    */
  4.  
  5. /* Reference:                */
  6. /*                    */
  7. /*    Kenneth E. Perry            */
  8. /*    Abstract Mathematical Art        */
  9. /*    BYTE                */
  10. /*    December, 1986            */
  11. /*    pages 181-192            */
  12.  
  13. /*    Copyright (C) 1987        */
  14. /*    Copyright (C) 1988        */
  15. /*    Harold V. McIntosh        */
  16. /*    Gerardo Cisneros S.        */
  17.  
  18. /* G. Cisneros, 4.3.87                        */
  19. /* 10 April 1987 - modified for (4,2) [HVM]            */
  20. /* 26 April 1987 - Multiple menus [HVM]                */
  21. /* 28 April 1987 - back modified to (4,1) [HVM]            */
  22. /* 28 April 1987 - version for XVI Feria de Puebla [HVM]    */
  23. /* 14 May 1987 - modified for (3,1) and general rule [HVM]    */
  24. /* 19 May 1987 - modified for (2,2) [HVM]            */
  25. /* 20 May 1987 - modified for (2,3) [HVM]            */
  26. /* 8 June 1987 - general rule for (4,1) [HVM]             */
  27. /* 12 June 1987 - cartesian product of (2,1) rules [HVM]    */
  28. /* 12 June 1987 - (2,1) rule with memory  [HVM]            */
  29. /* 14 June 1987 - individual cycles of evolution [HVM]        */
  30. /* 17 June 1987 - p-adic representation in plane [HVM]        */
  31. /* 22 June 1987 - 2 speed gliders via 16 transitions [HVM]    */
  32. /* 26 June 1987 - push, pop the rule [HVM]            */
  33. /* 26 June 1987 - conserve position of rule cursor [HVM]    */
  34. /* 27 June 1987 - incremental rule construction [HVM]        */
  35. /* 29 June 1987 - conserve position of cell pointer [HVM]    */
  36. /* 30 June 1987 - mark & unmark transitions, xchg x&X [HVM]    */
  37. /* 25 July 1987 - display and edit de Bruijn diagrams [HVM]    */
  38. /* 27 July 1987 - graph of transition probabilities [HVM]    */
  39. /* 4 September 1987 - PROB41.C for option 't' [HVM]        */
  40. /* 21 October 1987 - program disks disappeared            */
  41. /* 24 December 1987 - program reconstructed from listings    */
  42. /* 20 February 1988 - RIJN41.C for option 'd' [HVM]        */
  43.  
  44. # include <bdos.h>
  45.  
  46. # define COLGRAF     4  /* graph resolution            */
  47. # define T80X25      3  /* text resolution            */
  48. # define TRR        16  /* row showing totalistic rule number    */
  49. # define TRC        56  /* column for totalistic rule number    */
  50. # define XRR        12  /* row displaying totalistic rule    */
  51. # define XRC        56  /* column for totalistic rule        */
  52. # define WHCYMAG     1  /* color quad for normal screen        */
  53. # define YELREGR     2  /* color quad for alternative        */
  54. # define AL        320  /* array length (screen width)        */
  55. # define SL        40    /* short array length            */
  56. # define TS        10    /* distinct sums w/totalistic rule    */
  57. # define DS        64  /* (number of distinct neighborhoods)    */
  58. # define KK         4  /* number of states per cell        */
  59. # define NX         23    /* number of sample rules        */
  60.  
  61. char xrule[NX][KK][KK][KK];
  62.  
  63. char ixrule[NX][DS]=
  64.  
  65.     "0001130003122323023030102111030121230003323213211011302112211302",    /* gliders among stills */
  66.     "0001130130222132112122321212120102111201122311230301231030230321",    /* nice cross hatching */
  67.     "0001130130222132110101010332020102111201122311230301321030230321",    /* very complex glider */
  68.     "0010113231123333021220103301032113210101101221230033113223120103",    /* v. bars w/entanglement */
  69.     "0012121132220120212330123102202020121112101220322110011310022330",    /* cycles on dgl bgrnd    */
  70.     "0020100001230000232301210123321233001123121232112333110012300230",    /* crosshatching */
  71.     "0020103300113022002032300003303000201100101100100020100033002022",    /* bin ctr */
  72.     "0032121132220120212330123102202020121112101220322110011310022330",    /* cycles on dgl bgrnd    */
  73.     "0100000220200110010000000120212001003032210200103233300302330000",    /* shuttle squeeze */
  74.     "0100020010220131000220003020003001002020213230023230300000300010",    /* coo gldrs */
  75.     "0120120120130133120120130133133220130133133233230133133233233230",    /* Perry's #45 */
  76.     "0123011002000313130201120022032301210123132022101023332323210313",    /* crocodile skin */
  77.     "0123012312100211011101110101313101023121133220110233123110021210",    /* mixture of types */
  78.     "0123032103210123012302233111132103221112321133300311302020210323",    /* y/o on b/g */
  79.     "0203001212230010000300201010000000033020222320200000002020200000",    /* slow glider - copies bar */
  80.     "0203013021220020012201202120002200223122212211220013313032302333",    /* slow glider */
  81.     "0203022213220121002010302212013201233002210332010303132021002113",    /* slow & fast gliders */
  82.     "0203030213200201031323333233023200132331213223130233203011032120",    /* slo gl w/ many f gl */
  83.     "0212011232210112001012301310133112212232322211210000123200333230",
  84.     "0231231131121123231131121123123031121123123023001123123023003003",    /* Perry's blue background */
  85.     "0300101011130131202233320002313020212123201221110232112022303132",    /* diagonal growth on mesh */
  86.     "1010102020202020101011313131323232323121212132323231313130000000",    /* skewed triangle */
  87.     "2121123121332313323212113122230113201130210123320020122112012332"    /* gliderettes & latice */
  88.  
  89.     ;
  90.  
  91. char   tabl[20][SL];                    /* workspace to construct table */
  92. char   ascrule[KK][KK][KK];                /* ASCII transition values */
  93. char   auxrule[KK][KK][KK];                /* auxiliary transition table */
  94. char   rulstk[10][KK][KK][KK];                /* pushdown for rules */
  95. char   prule1[8], prule2[8];                /* product rule specification */
  96. char   trule[TS]="0130232113";
  97. int    binrule[KK][KK][KK];
  98. int    arr1[AL], arr2[AL];                /* line of cells */
  99. int    ru, ru0, ru1, ru2;                /* rule cursor */
  100. int    li, lj;                        /* cell pointer */
  101. int    rulptr;                        /* rule pd ptr */
  102. int    ix0, iy0;                    /* origin for pen moves */
  103. double wmul[KK], wmvl[KK];                /* left mass point */
  104. double wmur[KK], wmvr[KK];                /* right mass point */
  105. double bp[KK][KK][KK][KK];                /* bernstein polynomial */
  106.  
  107.  
  108. main() {
  109. int  i, j, i0, i1, i2, i3, i4, i5;
  110. int  more = 'r';
  111. char a, b, c;
  112.  
  113. ru=6; ru0=0; ru1=0; ru2=0;
  114. li=SL/2; lj=0;
  115. rulptr=0;
  116.  
  117. for (i=0; i<NX; i++) {                    /* copy to 3-index array */
  118. i0=0; i1=0; i2=0;
  119. for (j=0; j<DS; j++) {
  120.   xrule[i][i0][i1][i2]=ixrule[i][j];
  121.   i2++;
  122.   if (i2==KK) {i2=0; i1++;};
  123.   if (i1==KK) {i1=0; i0++;};
  124.   if (i0==KK) {i0=0; };
  125. };};
  126.  
  127.     videopalette(WHCYMAG);                /* white/cyan/magenta */
  128.  
  129.     tuto();
  130.     while (!kbdst()) rand();                /* wait for keypress */
  131.     kbdin();                        /* ignore it */
  132.     videomode(T80X25);
  133.     videoscroll(3,0,5,71,0,3);                /* menu on blue background */
  134.     videoscroll(19,0,24,71,0,3);
  135.     xtoasc(rand()%NX);
  136.     ranlin();                        /* random initial array */
  137.     auxblnk();                        /* uncomitted transitions */
  138.  
  139.     while (more!='n') {                    /* execute multiple runs */
  140.     rmenu();
  141.     lmenu();
  142.     while (0<1) {                    /* set up one run */
  143.     c=kbdin();
  144.     if (c=='g') break;                    /* go draw graph */
  145.     if (c=='q') more='n';                /* quit for good */
  146.     if (more=='n') break;
  147.     switch (c) {
  148.     case '@':                    /* numbered tot rule */
  149.         nutoto(numin(0));
  150.         totoasc();
  151.         rmenu();
  152.         videocursor(0,4,0);
  153.         break;
  154.     case '$':                    /* dozen totalistics */
  155.         j=numin(0);
  156.         for (i=0; i<12; i++) {
  157.           nutoto(j+i);
  158.           totoasc();
  159.           ranlin();
  160.           evolve();
  161.           };
  162.         videomode(T80X25);
  163.         rmenu();
  164.         lmenu();
  165.         break;
  166.     case '.':                    /* one cycle of evolution */
  167.         asctobin();
  168.         onegen(AL);
  169.         clmenu();
  170.         pprob();
  171.         break;
  172.     case ',':                    /* one cycle of evolution */
  173.         videomode(COLGRAF);
  174.         pgrid();
  175.         for (i=0; i<200; i++) {pprob(); onegen(AL);};
  176.         videodot(190,195,3);
  177.         kbdin();
  178.         videomode(T80X25);
  179.         rmenu();
  180.         lmenu();
  181.         break;
  182.     case 'T':                    /* totalistic rule */
  183.         xblnk();
  184.         tmenu();
  185.         edtrule();
  186.         totoasc();
  187.         for (i0=0; i0<KK; i0++) {
  188.         for (i1=0; i1<KK; i1++) {
  189.         for (i2=0; i2<KK; i2++) {
  190.         ascrule[i0][i1][i2]=trule[i0+i1+i2];
  191.         };};};
  192.         videocursor(0,4,0);
  193.         rmenu();
  194.         xmenu(totonu(0));
  195.         break;
  196.     case 't':                    /* triangular probability graph */
  197.         edtri();
  198.         rmenu();
  199.         lmenu();
  200.         break;
  201.     case 'p':                    /* product of two (2,1) rules */
  202.         nutowo1(numin(0));
  203.         nutowo2(numin(0));
  204.         for (i0=0; i0<2; i0++) {
  205.         for (i1=0; i1<2; i1++) {
  206.         for (i2=0; i2<2; i2++) {
  207.         for (i3=0; i3<2; i3++) {
  208.         for (i4=0; i4<2; i4++) {
  209.         for (i5=0; i5<2; i5++) {
  210.         ascrule[2*i0+i1][2*i2+i3][2*i4+i5]='0'+2*(prule1[4*i0+2*i2+i4]-'0')+(prule2[4*i1+2*i3+i5]-'0');
  211.         };};};};};};
  212.         xblnk();
  213.         rmenu();
  214.         break;
  215.     case 'm':                    /* (2,1) rules with memory */
  216.         nutowo1(numin(0));
  217.         for (i0=0; i0<2; i0++) {
  218.         for (i1=0; i1<2; i1++) {
  219.         for (i2=0; i2<2; i2++) {
  220.         for (i3=0; i3<2; i3++) {
  221.         for (i4=0; i4<2; i4++) {
  222.         for (i5=0; i5<2; i5++) {
  223.         ascrule[2*i0+i1][2*i2+i3][2*i4+i5]='0'+2*(prule1[4*i0+2*i2+i4]-'0')+i2;
  224.         };};};};};};
  225.         xblnk();
  226.         rmenu();
  227.         break;
  228.         case 'r':                    /* edit rule */    
  229.         xblnk();
  230.         edrule();
  231.         videocursor(0,4,0);
  232.         rmenu();
  233.         break;
  234.         case 'l':                    /* edit cell string */
  235.         xblnk();
  236.         edline(8,40);
  237.         videocursor(0,3,0);
  238.         lmenu();
  239.         break;
  240.         case '#':                    /* read stored rule */
  241.         xmenu(NX);
  242.         xtoasc(lim(1,numin(0),NX)-1);
  243.         rmenu();
  244.             break;
  245.     case 'D':                    /* run through samples */
  246.         for (i=0; i<NX; i++) {
  247.           xmenu(i);
  248.           xtoasc(i);
  249.           ranlin();
  250.           evolve();
  251.           };
  252.         videomode(T80X25);
  253.         rmenu();
  254.         break;
  255.     case 'd':                    /* de Bruijn diagram */
  256.         edijn();
  257.         rmenu();
  258.         lmenu();
  259.         break;
  260.         case 'u':                    /* sparse init arry */
  261.         xblnk();
  262.         for (i=0; i<AL; i++) arr1[i]=0;
  263.         arr1[AL/4]=1;
  264.             arr1[AL/2]=1;
  265.             arr1[(3*AL)/4]=1;
  266.             arr1[(3*AL)/4+2]=1;
  267.         lmenu();
  268.             break;
  269.     case 'X':                    /* random rule */
  270.         xblnk();
  271.         i=rand();
  272.         for (i0=0; i0<KK; i0++) {
  273.         for (i1=0; i1<KK; i1++) {
  274.         for (i2=0; i2<KK; i2++) {
  275.           if (i == 0) i=rand();
  276.           ascrule[i0][i1][i2]='0'+i%KK;
  277.           i/=KK;
  278.         };};};
  279.         rmenu();
  280.         break;
  281.     case 'x':                    /* random rule */
  282.         xblnk();
  283.         for (i0=0; i0<KK; i0++) {
  284.         for (i1=0; i1<KK; i1++) {
  285.         for (i2=0; i2<KK; i2++) {
  286.           if (i == 0) i=rand();
  287.           if (auxrule[i0][i1][i2]==' ') {
  288.         ascrule[i0][i1][i2]='0'+i%KK;
  289.         i/=KK;
  290.         };
  291.           };};};
  292.         rmenu();
  293.         break;
  294.     case 'y':                    /* random line */
  295.         xblnk();
  296.         ranlin();
  297.             lmenu();
  298.         break;
  299.     case 'z':
  300.         for (i=0; i<AL; i++) arr1[i]=0;
  301.         lmenu();
  302.         break;
  303.     case 'Y':                    /* symmetrize rule */
  304.         for (i0=0; i0<KK; i0++) {
  305.         for (i1=0; i1<KK; i1++) {
  306.         for (i2=0; i2<KK; i2++) {
  307.         ascrule[i2][i1][i0]=ascrule[i0][i1][i2];      
  308.         };};};
  309.         rmenu();
  310.         break;
  311.     case 'B':                    /* begin barrier */
  312.         a=kbdin();
  313.         b=kbdin();
  314.         ascrule[0][a-'0'][b-'0']=a;
  315.         ascrule[1][a-'0'][b-'0']=a;
  316.         ascrule[2][a-'0'][b-'0']=a;
  317.         ascrule[3][a-'0'][b-'0']=a;
  318.         rmenu();
  319.         break;
  320.     case 'E':                    /* end barrier */
  321.         a=kbdin();
  322.         b=kbdin();
  323.         ascrule[a-'0'][b-'0'][0]=b;
  324.         ascrule[a-'0'][b-'0'][1]=b;
  325.         ascrule[a-'0'][b-'0'][2]=b;
  326.         ascrule[a-'0'][b-'0'][3]=b;
  327.         rmenu();
  328.         break;
  329.     case 'L':                    /* left glider link */
  330.         a=kbdin();
  331.         b=kbdin();
  332.         c=kbdin();
  333.         ascrule[a-'0'][b-'0'][c-'0']=c;
  334.         rmenu();
  335.         break;
  336.     case 'R':                    /* left glider link */
  337.         a=kbdin();
  338.         b=kbdin();
  339.         c=kbdin();
  340.         ascrule[a-'0'][b-'0'][c-'0']=a;
  341.         rmenu();
  342.         break;
  343.     case 'S':                    /* still life link */
  344.         a=kbdin();
  345.         b=kbdin();
  346.         c=kbdin();
  347.         ascrule[a-'0'][b-'0'][c-'0']=b;
  348.         rmenu();
  349.         break;
  350.     case 'U':                    /* push rule */
  351.         if (rulptr<10) rulptr++;
  352.         for (i0=0; i0<KK; i0++) {
  353.         for (i1=0; i1<KK; i1++) {
  354.         for (i2=0; i2<KK; i2++) {
  355.         rulstk[rulptr][i0][i1][i2]=ascrule[i0][i1][i2];
  356.         };};};
  357.         xmenu(rulptr);
  358.         break;
  359.     case 'V':                    /* pop rule */
  360.         for (i0=0; i0<KK; i0++) {
  361.         for (i1=0; i1<KK; i1++) {
  362.         for (i2=0; i2<KK; i2++) {
  363.         ascrule[i0][i1][i2]=rulstk[rulptr][i0][i1][i2];
  364.         };};};
  365.         if (rulptr>0) rulptr--;
  366.         rmenu();
  367.         break;
  368.     case 'G':                    /* fetch rule */
  369.         for (i0=0; i0<KK; i0++) {
  370.         for (i1=0; i1<KK; i1++) {
  371.         for (i2=0; i2<KK; i2++) {
  372.         ascrule[i0][i1][i2]=rulstk[rulptr][i0][i1][i2];
  373.         };};};
  374.         rmenu();
  375.         break;
  376.     case '1':
  377.         ascrule[0][0][0]='0';
  378.         ascrule[0][0][1]='0';
  379.         ascrule[0][0][2]='0';
  380.         ascrule[0][0][3]='1';
  381.         ascrule[0][1][0]='1';
  382.         ascrule[0][1][1]='2';
  383.         ascrule[0][1][3]='1';
  384.         ascrule[0][2][0]='3';
  385.         ascrule[0][3][1]='1';
  386.         ascrule[1][0][0]='1';
  387.         ascrule[1][1][1]='0';
  388.         rmenu();
  389.         break;
  390.     case '2':
  391.         ascrule[0][0][0]='0';
  392.         ascrule[0][0][1]='2';
  393.         ascrule[0][0][2]='0';
  394.         ascrule[0][0][3]='3';
  395.         ascrule[0][1][0]='0';
  396.         ascrule[0][1][3]='2';
  397.         ascrule[0][2][0]='1';
  398.         ascrule[0][2][2]='2';
  399.         ascrule[0][3][0]='0';
  400.         ascrule[1][0][0]='0';
  401.         ascrule[1][0][3]='3';
  402.         ascrule[1][3][0]='0';
  403.         ascrule[2][0][0]='0';
  404.         ascrule[2][0][3]='3';
  405.         ascrule[2][2][0]='2';
  406.         ascrule[3][0][0]='0';
  407.         rmenu();
  408.         break;
  409.     case '=':
  410.         for (i=1; i<8;  i++) {
  411.         for (j=0; j<SL; j++) arr1[SL*i+j]=arr1[j];};
  412.         lmenu();
  413.         break;
  414.     case ':':
  415.         for (i=1; i<16;  i++) {
  416.         for (j=0; j<20; j++) arr1[20*i+j]=arr1[j];};
  417.         lmenu();
  418.         break;
  419.     case ';':
  420.         for (i=1; i<32;  i++) {
  421.         for (j=0; j<10; j++) arr1[10*i+j]=arr1[j];};
  422.         lmenu();
  423.         break;
  424.         default: break;
  425.         };
  426.     };
  427.     if (more=='n') break;
  428.     do {
  429.     evolve();
  430.     videocursor(0,0,0);
  431.     scrstr("?");
  432.     videocursor(0,0,34);
  433.     scrstr("y/n/cr");
  434.     more=kbdin();
  435.     } while (more=='\015');
  436.     videomode(T80X25);                    /* reset the screen */
  437.     if (more=='n') break;
  438.     };
  439.   videomode(T80X25);}    
  440.  
  441. /* edit the rule */
  442. edrule() {char c;
  443.   while (0<1) {
  444.     cscrrul();
  445.     videocursor(0,3,ru);
  446.     c=kbdin();
  447.     if (c=='\015') break;                /* carriage return exits */
  448.     switch (c) {
  449.     case '0': case '1': case '2': case '3':        /* state */
  450.       ascrule[ru0][ru1][ru2]=c;
  451.       videocattr(0,c,3,1);
  452.       rupl();
  453.       break;
  454.     case '\011':                    /* tab = next quad */
  455.       ru2=0; ru1=0; ru0++;
  456.       if (ru0==KK) ru0=0;
  457.       ru=KK*KK*ru0+6;
  458.       break;
  459.     case ' ': case '\315': rupl(); break;        /* space = advance */
  460.     case '\010': case '\313': rumi(); break;        /* backspace */
  461.     case '\013': case '\310': auxrule[ru0][ru1][ru2]='+'; break; /* up arrow */
  462.     case '\012': case '\320': auxrule[ru0][ru1][ru2]=' '; break; /* down arrow */
  463.     default: break;
  464.     };
  465.   };
  466. }
  467.  
  468. /* advance the rule cursor */
  469. rupl() {
  470.   ru2++;
  471.   if (ru2==KK) {ru2=0; ru1++;};
  472.   if (ru1==KK) {ru1=0; ru0++;};
  473.   if (ru0==KK) {ru0=0; };
  474.   ru=KK*(KK*ru0+ru1)+ru2+6;
  475.   }
  476.  
  477. /* retract the rule cursor */
  478. rumi() {
  479.   if (ru2!=0) ru2--; else {ru2=KK-1;
  480.   if (ru1!=0) ru1--; else {ru1=KK-1;
  481.   if (ru0!=0) ru0--; else {ru0=KK-1;
  482.      };};};
  483.   ru=KK*(KK*ru0+ru1)+ru2+6;
  484.   }
  485.  
  486. /* edit totalistic rule */
  487. edtrule() {char c; int  i, j;
  488.   i=0;
  489.   while (i<TS) {
  490.     c=trule[i];
  491.     videocursor(0,TRR,TRC+i);
  492.     videocattr(0,c,3,1);
  493.     c=kbdin();
  494.     if (c=='\015') break;
  495.     switch (c) {
  496.       case '0': case '1': case '2': case '3':        /* state */
  497.         trule[i]=c;
  498.         videocattr(0,c,2,1);
  499.         i++; break;
  500.       case ' ': case '\315':                /* space = advance */
  501.         i++; break;
  502.       case '\010': case '\313':                /* backspace */
  503.         if (i!=0) i--;
  504.         break;
  505.       case 'x':                        /* random rule */
  506.     i=rand();
  507.     for (j=0; j<TS; j++) {
  508.       if (i==0) i=rand();
  509.       trule[j]='0'+i%KK;
  510.       i/=KK;
  511.       };
  512.     tmenu();
  513.     break;
  514.       default: break;
  515.       };
  516.     };
  517. }
  518.  
  519. /* edit the line of cells */
  520. edline(nr,nc) int nr, nc; {
  521. char c;
  522. int  i, j, k, l, m;
  523. int  aa, bb, cc;
  524. int  xx, yy, zz;
  525.  
  526.   m=0;
  527.   videocursor(0,19,0);
  528.   scrstr("insert states with 0, 1, 2, 3; move cursor");
  529.   videocursor(0,20,0);
  530.   scrstr("with keyboard arrows, space or backspace.");
  531.   videocursor(0,21,0);
  532.   scrstr("carriage return exits");
  533.   while (0<1) {
  534.   videocursor(0,lj+9,li);
  535.   c=kbdin();
  536.   if (c == '\015') {videoscroll(19,0,24,70,0,3); break;};
  537.   switch (c) {
  538.   case '0': case '1': case '2': case '3': arr1[nc*lj+li]=c-'0'; break;    /* enter state */
  539.   case '\012': case '\320':        if (lj<nr-1) lj++; break;    /* down    */
  540.   case '\013': case '\310':        if (lj>0)    lj--; break;    /* up      */
  541.   case '\014': case '\315': case ' ':    if (li<nc-1) li++; break;    /* forward */
  542.   case '\010': case '\313':        if (li>0)    li--; break;    /* back    */
  543.   case '<': li=0;    break; /* left margin */
  544.   case '>': li=nc-1; break; /* right margin */
  545.   case 'z': for (k=0; k<nc; k++) arr1[nc*lj+k]=0; break;            /* clear row */
  546.   case 'Z': for (k=0; k<AL; k++) arr1[k]=0; lmenu(); break;
  547.   case '^': for (k=0; k<nc; k++) arr1[nc*lj+k]=arr1[nc*(lj-1)+k]; break;
  548.   case 'x': auxblnk(); break;                 /* uncomitted transitions */
  549.   case 'q': ulmenu(3); break;                 /* uniform line menu */
  550.   case '=':                         /* insert point transition */
  551.     if (lj==0) break;
  552.     yy=li+nc*(lj-1);
  553.     xx=li==0?yy+nc-1:yy-1;
  554.     zz=li==nc-1?yy-nc+1:yy+1;
  555.     c=arr1[yy+nc]+'0';
  556.     ascrule[arr1[xx]][arr1[yy]][arr1[zz]]=c;
  557.     auxrule[arr1[xx]][arr1[yy]][arr1[zz]]=c;
  558.     rmenu(); 
  559.     videocursor(0,lj+9,li);
  560.     videocattr(0,arr1[yy+nc],3,1);
  561.     cscrrul();
  562.     break;
  563.   case '*':                        /* insert transition */
  564.     if (lj==0) break;
  565.     for (i=0; i<nc; i++) {
  566.       yy=i+nc*(lj-1);
  567.       xx=i==0?yy+nc-1:yy-1;
  568.       zz=i==nc-1?yy-nc+1:yy+1;
  569.       c=arr1[yy+nc]+'0';
  570.       ascrule[arr1[xx]][arr1[yy]][arr1[zz]]=c;
  571.       auxrule[arr1[xx]][arr1[yy]][arr1[zz]]=c;
  572.       videocattr(0,arr1[yy+nc],3,1);
  573.       };
  574.     rmenu(); 
  575.     videocursor(0,lj+9,li);
  576.     cscrrul();
  577.     break;
  578.   case '.':                        /* point evolution */
  579.     if (lj==0) break;
  580.     yy=li+nc*(lj-1);
  581.     xx=li==0?yy+nc-1:yy-1;
  582.     zz=li==nc-1?yy-nc+1:yy+1;
  583.     arr1[yy+nc]=ascrule[arr1[xx]][arr1[yy]][arr1[zz]]-'0';
  584.     break;
  585.   case '?':                        /* evolution of whole line */
  586.     if (lj==nr-1) {for (i=0; i<AL-nc; i++) arr1[i]=arr1[i+nc]; lj--; lmenu(); };
  587.     lj++;
  588.     for (i=0; i<nc; i++) {
  589.       yy=i+nc*(lj-1);
  590.       xx=i==0?yy+nc-1:yy-1;
  591.       zz=i==nc-1?yy-nc+1:yy+1;
  592.       arr1[yy+nc]=ascrule[arr1[xx]][arr1[yy]][arr1[zz]]-'0';
  593.       };
  594.     break;
  595.   case '/':                        /* conditional evolution */
  596.     if (lj==nr-1) {for (k=0; k<AL-nc; k++) arr1[k]=arr1[k+nc]; lj--; lmenu(); };
  597.     lj++;
  598.     for (i=0; i<nc; i++) {
  599.       j=0;
  600.       yy=i+nc*(lj-1);
  601.       xx=i==0?yy+nc-1:yy-1;
  602.       zz=i==nc-1?yy-nc+1:yy+1;
  603.       aa=arr1[xx]; if (aa>KK-1) j=KK;
  604.       bb=arr1[yy]; if (bb>KK-1) j=KK;
  605.       cc=arr1[zz]; if (cc>KK-1) j=KK;
  606.       if (auxrule[aa][bb][cc]==' ') j=KK;
  607.       if (j==0) j=ascrule[aa][bb][cc]-'0';
  608.       arr1[yy+nc]=j;
  609.       };
  610.     break;
  611.   case 'c':                        /* test consistency */
  612.     for (i=0; i<nc; i++) {
  613.       videocursor(0,9,i);
  614.       k=arr1[i];
  615.       videocattr(0,k==0?'.':k+'0',7,1);
  616.       };
  617.     for (j=1; j<8;  j++) {
  618.     for (i=0; i<nc; i++) {
  619.       yy=i+nc*(j-1);
  620.       xx=i==0?yy+nc+1:yy+1;
  621.       aa=arr1[xx];
  622.       bb=arr1[yy];
  623.       cc=arr1[zz];
  624.       k=arr1[yy+nc];
  625.       videocursor(0,j+9,i);
  626.       videocattr(0,k==0?'.':k+'0',k==ascrule[aa][bb][cc]-'0'?7:4,1);
  627.       };};
  628.     m=1;
  629.     break;
  630.   case 'C':                        /* test consistency */
  631.     for (i=0; i<nc; i++) {
  632.       videocursor(0,9,i);
  633.       k=arr1[i];
  634.       videocattr(0,k==0?'.':k+'0',7,1);
  635.       };
  636.     for (j=1; j<8;  j++) {
  637.     for (i=0; i<nc; i++) {
  638.       yy=i+nc*(j-1);
  639.       xx=i==0?yy+nc+1:yy+1;
  640.       aa=arr1[xx];
  641.       bb=arr1[yy];
  642.       cc=arr1[zz];
  643.       k=arr1[yy+nc];
  644.       videocursor(0,j+9,i);
  645.       videocattr(0,k==0?'.':k+'0',
  646.         (k==ascrule[aa][bb][cc]-'0' && auxrule[aa][bb][cc]!=' ')?7:4,1);
  647.       };};
  648.     m=1;
  649.     break;
  650.   default: break;
  651.       }; /* end switch */
  652.   if (m==0) for (k=0; k<nc; k++) {
  653.     videocursor(0,lj+9,k);
  654.     l=arr1[nc*lj+k]+'0';
  655.     videoputc(l=='0'?'.':l,1);
  656.     };
  657.   m=0;
  658.   }; /* end while */
  659. } /* end edline */
  660.  
  661. /* display a screen of evolution */
  662. evolve() {int i, j;
  663.   videomode(COLGRAF);                    /* erase the screen */
  664.   videocursor(0,0,0);                    /* top text line */
  665.   scrstr(":");
  666.   hscrrul();
  667.   asctobin();
  668.   for (j=8; j<200; j++) videodot(j,AL-1,2);
  669.   for (j=8; j<200; j++) {                /* evolve for 192 generations */
  670.     for (i=0; i<AL; i++) videodot(j,i,arr1[i]);
  671.     onegen(AL);
  672.     if (kbdst()) {kbdin(); break;};
  673.     };
  674. }
  675.  
  676. /* copy ascrule over to binrul */
  677. asctobin() {int i0, i1, i2;
  678.   for (i0=0; i0<KK; i0++) {
  679.   for (i1=0; i1<KK; i1++) {
  680.   for (i2=0; i2<KK; i2++) {
  681.     binrule[i0][i1][i2]=ascrule[i0][i1][i2]-'0';
  682.     };};};
  683. }
  684.  
  685. /* evolution for one generation */
  686. onegen(j) int j; {int i;
  687.   if (j<2) return;
  688.   arr2[0]=binrule[arr1[j-1]][arr1[0]][arr1[1]];
  689.   for (i=1; i<j-1; i++) arr2[i]=binrule[arr1[i-1]][arr1[i]][arr1[i+1]];
  690.   arr2[j-1]=binrule[arr1[j-2]][arr1[j-1]][arr1[0]];
  691.   for (i=0; i<j; i++) arr1[i]=arr2[i];
  692. }
  693.  
  694. /* map the automaton state into the unit square */
  695. pprob() {int i, j; float x, y, z, k;
  696. i=AL/2; k=(float)KK; z=(float)((197/(KK*KK))*KK*KK);
  697. x=0.0; for (j=1; j<30; j++) x=(x+(float)arr1[i+j])/k;
  698. y=0.0; for (j=1; j<30; j++) y=(y+(float)arr1[i-j])/k;
  699. x=(x+(float)arr1[i])/k;
  700. videodot((int)(z*(1.0-y)),(int)(z*x),1);
  701. }
  702.  
  703. /* set up a grid for the unit square */
  704. pgrid() {int i, j, k, l;
  705. k=KK*KK+1;
  706. l=195/(k-1);
  707. for (i=0; i<k; i++) {
  708. for (j=0; j<k; j++) {
  709. videodot(l*i,l*j,2);
  710. };};
  711. }
  712.  
  713. /* tutorial and Help screen */
  714. tuto() {
  715.     videomode(T80X25);
  716.     videocursor(0,2,0);
  717.     scrstr("<Copyright (C) 1987, 1988 - H.V.McIntosh, G.Cisneros S.>");
  718.     videocursor(0,4,0);
  719.     scrstr("             *** LIFE in One Dimension ***");
  720.     videocursor(0,6,0);
  721.     scrstr("Four States - Black(0), Cyan(1), Magenta(2), White(3).");
  722.     videocursor(0,8,0);
  723.     scrstr("First neighbors - one on each side, three altogether.");
  724.     videocursor(0,10,0);
  725.     scrstr("Complete transition rule - random, edited, or stored.");
  726.     videocursor(0,12,0);
  727.     scrstr("Totalistic transition rule - random, edited, or stored.");
  728.     videocursor(0,14,0);
  729.     scrstr("Initial Cellular Array - random, edited, or patterned.");
  730.     videocursor(0,16,0);
  731.     scrstr("Submenus in options t(probabilities) and d(de Bruijn)");
  732.     videocursor(0,17,0);
  733.     scrstr("will be displayed in response to typing ?");
  734.     videocursor(0,19,0);
  735.     scrstr("Use any key to terminate a display in progress.");
  736.     videocursor(0,22,0);
  737.     scrstr("now, ... press any key to continue.");
  738. }
  739.  
  740. /* rule menu */
  741. rmenu() {
  742.     videocursor(0,0,0);
  743.     scrstr("      0000000000000000111111111111111122222222222222223333333333333333");
  744.     videocursor(0,1,0);
  745.     scrstr("      0000111122223333000011112222333300001111222233330000111122223333");
  746.     videocursor(0,2,0);
  747.     scrstr("      0123012301230123012301230123012301230123012301230123012301230123");
  748.     videocursor(0,3,0);
  749.     scrstr("Rule: ");
  750.     scrrul();
  751.     if (istot()==1) {videocursor(0,TRR,TRC); xmenu(totonu(0));};
  752.     videocursor(0,5,0);
  753.     scrstr("    r(rule), l(line), #nn(stored), g(graph), q(quit), t(prob),");
  754.     videocursor(0,6,0);
  755.     scrstr("           x(rand rule), y(rand line), u(unit line), d(deBruijn)");
  756.     videocursor(0,7,0);
  757.     scrstr("           @nn(tot/rule), $nn(12 tot/rules), T(ed tot/rule).");
  758.     videocursor(0,5,0);
  759.     }
  760.  
  761. /* totalistic rule menu*/
  762. tmenu() {
  763.     videocursor(0,TRR-2,TRC-6);
  764.     scrstr("      totalistic rule");
  765.     videocursor(0,TRR-1,TRC-6);
  766.     scrstr("      0..1..2..3");
  767.     videocursor(0,TRR,TRC-6);
  768.     scrstr("rule: ");
  769.     tscrrul();
  770.     videocursor(0,TRR,TRC);
  771.     }
  772.  
  773. /* plain line menu */
  774. lmenu() {int i, j; char c;
  775.   for (j=0; SL*j<AL; j++) {videocursor(0,9+j,0);
  776.   for (i=0; i<SL; i++) {c='0'+arr1[SL*j+i]; videoputc(c=='0'?'.':c,1); }; };
  777.   videocursor(0,5,0); }
  778.  
  779. /* uniform line menu */
  780. ulmenu(l) int l; {int i, j, k;
  781.   for (j=0; j*SL<AL; j++) {
  782.   for (i=0; i<SL;    i++) {
  783.     videocursor(0,9+j,i);
  784.     k=arr1[j*SL+i];
  785.     videocattr(0,k==0?'.':k+'0',l,1);
  786.     };};
  787.   }
  788.  
  789. /* color line menu */
  790. clmenu() {int c, i, j;
  791.   for (j=0; SL*j<AL; j++) {
  792.     for (i=0; i<SL; i++) {
  793.       videocursor(0,9+j,i);
  794.       c=arr1[SL*j+i];
  795.       videocattr(0,c==0?'.':'0'+c,color(c),1);
  796.       };};
  797.   videocursor(0,5,0); }
  798.  
  799. /* get compatible color */
  800. int color(i) int i; {
  801.   switch (i) {
  802.     case 0:  return 2;
  803.     case 1:  return 3;
  804.     case 2:  return 5;
  805.     case 3:  return 7;
  806.     default: return 6;
  807. };}
  808.  
  809. /* display rule number */
  810. xmenu(n) int n; {
  811. char xx[6];
  812. int i, nn;  
  813.     nn=sprintf(xx,"%5u",n);
  814.     videocursor(0,XRR,XRC);
  815.     for (i=0; i<nn; i++) videoputc(xx[i],1);
  816.     videocursor(0,XRR,XRC); }
  817.  
  818. /* clear screen space for rule number */
  819. xblnk() {videocursor(0,XRR,XRC); scrstr("     "); videocursor(0,5,0); }
  820.  
  821. /* copy saved rule #n into active rule */
  822. xtoasc(n) int n; {int i0, i1, i2;
  823.     xmenu(n+1);
  824.     for (i0=0; i0<KK; i0++) {
  825.     for (i1=0; i1<KK; i1++) {
  826.     for (i2=0; i2<KK; i2++) {
  827.     ascrule[i0][i1][i2]=xrule[n][i0][i1][i2];
  828.     };};}; }
  829.  
  830. /* change totalistic rule to general rule */
  831. totoasc() {
  832. int i0, i1, i2;
  833. for (i0=0; i0<KK; i0++) {
  834. for (i1=0; i1<KK; i1++) {
  835. for (i2=0; i2<KK; i2++) {
  836. ascrule[i0][i1][i2]=trule[i0+i1+i2];
  837. };};};
  838. }
  839.  
  840. /* change decimal totalistic rule to sum values */
  841. nutoto(x) int x; {int i;
  842. for (i=0; i<TS; i++) {trule[i]=x%KK+'0'; x/=KK;};}
  843.  
  844. /* change sum values to decimal totalistic rule */
  845. int totonu(i) int i; {int r;
  846.   if (i<TS) r=(trule[i]-'0')+KK*totonu(i+1); else r=0;
  847.   return r; }
  848.  
  849. /* test whether a rule is totalistic */
  850. int istot() {int i0, i1, i2, l;
  851.     l=1;
  852.     trule[0]=ascrule[0][0][0];
  853.     trule[1]=ascrule[1][0][0];
  854.     trule[2]=ascrule[2][0][0];
  855.     trule[3]=ascrule[3][0][0];
  856.     trule[4]=ascrule[3][1][0];
  857.     trule[5]=ascrule[3][2][0];
  858.     trule[6]=ascrule[3][3][0];
  859.     trule[7]=ascrule[3][3][1];
  860.     trule[8]=ascrule[3][3][2];
  861.     trule[9]=ascrule[3][3][3];
  862.     for (i0=0; i0<KK; i0++) {
  863.     for (i1=0; i1<KK; i1++) {
  864.     for (i2=0; i2<KK; i2++) {
  865.     if (ascrule[i0][i1][i2]!=trule[i0+i1+i2]) l=0;
  866.     };};};
  867.     return l; }
  868.  
  869. /* generate a random line of cells in arr1 */
  870. ranlin() {int i, c;
  871. for (i=0; i<AL; i++) {
  872.   if (i%8 == 0) c=rand();
  873.   arr1[i]=c%KK; c/=KK;};
  874. }
  875.  
  876. /* clear auxrule to blanks */
  877. auxblnk() {int i0, i1, i2;
  878. for (i0=0; i0<KK; i0++) {
  879. for (i1=0; i1<KK; i1++) {
  880. for (i2=0; i2<KK; i2++) {
  881. auxrule[i0][i1][i2]=' ';
  882. };};};
  883. }
  884.  
  885. /* limit j to interval (i,k) */
  886. int lim(i,j,k) int i, j, k;
  887.     {if (i>=j) return i; if (k<=j) return k; return j;}
  888.  
  889. /* display the rule number on the screen */
  890. scrrul() {int i0, i1, i2;
  891.   for (i0=0; i0<KK; i0++) {
  892.   for (i1=0; i1<KK; i1++) {
  893.   for (i2=0; i2<KK; i2++) {
  894.   videoputc(ascrule[i0][i1][i2],1);
  895.   };};}; }
  896.  
  897. /* display the rule number on the screen in glorious technicolor */
  898. cscrrul() {int i, i0, i1, i2;
  899.   i=6;
  900.   for (i0=0; i0<KK; i0++) {
  901.   for (i1=0; i1<KK; i1++) {
  902.   for (i2=0; i2<KK; i2++) {
  903.   videocursor(0,3,i++);
  904.   videocattr(0,ascrule[i0][i1][i2],auxrule[i0][i1][i2]==' '?3:6,1);
  905.   };};}; }
  906.  
  907. /* display the hexadecimal rule number on the screen */
  908. hscrrul() {char i; int i0, i1, i2;
  909.   for (i0=0; i0<KK; i0++) {
  910.   for (i1=0; i1<KK; i1++) {
  911.   for (i2=0; i2<KK; i2+=2) {
  912.   i=ascrule[i0][i1][i2]+4*(ascrule[i0][i1][i2+1]-'0');
  913.   if (i>'9') i=i+('A'-':');
  914.   videoputc(i,1);      
  915.   };};}; }
  916.  
  917. /* display totalistic rule number by sum */
  918. tscrrul() {int i;
  919.   for (i=0; i<TS; i++) {videoputc(trule[i],1); }; }
  920.  
  921. /* change decimal totalistic rule to sum values */
  922. nutowo1(x) int x; {int i;
  923. for (i=0; i<TS; i++) {prule1[i]=x%2+'0'; x/=2;};}
  924.  
  925. /* change Wolfram rule number decimal rule number */
  926. int wotonu1(i) int i; {int r;
  927.   if (i<TS) r=(prule1[i]-'0')+2*totonu(i+1); else r=0;
  928.   return r; }
  929.  
  930. /* change decimal number to Wolfram rule number */
  931. nutowo2(x) int x; {int i;
  932. for (i=0; i<TS; i++) {prule2[i]=x%2+'0'; x/=2;};}
  933.  
  934. /* change sum values to decimal totalistic rule */
  935. int wotonu2(i) int i; {int r;
  936.   if (i<TS) r=(prule2[i]-'0')+2*totonu(i+1); else r=0;
  937.   return r; }
  938.  
  939. /* write a string in graphics mode */
  940. scrstr(s) char *s;
  941.   {for (; *s != '\0'; s++) videoputc(*s,1); }
  942.  
  943. /* keyboard status */
  944. int kbdst() {return(bdos(11) & 0xFF);}
  945.  
  946. /* direct keyboard input, no echo */
  947. kbdin() {int c;
  948.   if ((c = bdos(7) & 0xFF) == '\0') c = (bdos(7) & 0xFF) | 0x80;
  949.   return(c);
  950. }
  951.  
  952. /* read number from keyboard */
  953. int numin(n) int n; {char c;
  954.   c=kbdin();
  955.   if (c>='0'&&c<='9') return(numin(10*n+(c-'0'))); else return(n);
  956. }
  957.  
  958. # include "prob41.c"
  959. # include "rijn41.c"
  960.  
  961. /* end */
  962.